package com.ma.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * @ClassName ThreadTest
 * @Author: mayongqiang
 * @DATE 2021/9/22 19:43
 * @Description:
 */

public class ThreadTest {

    //当前系统中池只有一两个，每个异步任务直接提交给线程池，让他自己去执行
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main.....start.....");
        //创建异步任务
        //CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        //    System.out.println("当前线程：" + Thread.currentThread().getId());
        //    int i = 10 / 2;
        //    System.out.println("运行结果：" + i);
        //}, executor);

        //CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        //    System.out.println("当前线程：" + Thread.currentThread().getId());
        //    int i = 10 / 0;
        //    System.out.println("运行结果：" + i);
        //    return i;
        //}, executor).whenComplete((result,exception)->{
        //    //类似于监听器，虽然能得到异常信息，但是没法修改返回数据
        //    System.out.println("异步任务成功完成了,结果是："+result+"异常是："+exception);
        //}).exceptionally(throwable -> {
        //    //可以感知异常，同时返回默认值
        //    return 10;
        //});

        /**
         * 回调handle()：方法执行完成后的处理
         * */
        //CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        //    System.out.println("当前线程：" + Thread.currentThread().getId());
        //    int i = 10 / 0;
        //    System.out.println("运行结果：" + i);
        //    return i;
        //}, executor).handle((res,thr)->{
        //    if(res!=null){
        //        return res*2;
        //    }
        //    if(thr!=null){
        //        return 0;
        //    }
        //    return 0;
        //});
        /**
         * 线程串行化：
         * 1、thenRunAsync 不能获取到上一步的执行结果，无返回值
         *      .thenRunAsync(() -> {
         *             System.out.println("任务2启动了");
         *         }, executor);
         * 2、thenAcceptAsync 能接受上一步的结果，无返回值
         * 3、thenApplyAsync 能接受上一步的结果，有 返回值
         * */
        //CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        //    System.out.println("当前线程：" + Thread.currentThread().getId());
        //    int i = 10 / 2;
        //    System.out.println("运行结果：" + i);
        //    return i;
        //}, executor).thenApplyAsync(res -> {
        //    System.out.println("任务2启动了" + res);
        //    return "hello" + res;
        //}, executor);
        //String s = future.get();
        //System.out.println("main.....end....."+s);
        /**
         * 两个都完成
        // * */
        //CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
        //    System.out.println("任务1线程：" + Thread.currentThread().getId());
        //    int i = 10 / 2;
        //    System.out.println("任务1结束：" + i);
        //    return i;
        //}, executor);
        //
        //CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
        //    System.out.println("任务2线程：" + Thread.currentThread().getId());
        //    System.out.println("任务2结束：");
        //    return "hello";
        //}, executor);
        //
        //future01.runAfterBothAsync(future02,()->{
        //    System.out.println("任务3开始........");
        //},executor);
        //System.out.println("main.....end.....");
        CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("图片");
            return "hello.jpg";
        });

    }


    public static void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main.....start.....");
        /**
         * 1）、继承 Thread
         *         Thread01 thread = new Thread01();
         *         thread.start();
         *
         * 2）、实现 Runnable 接口
         *         Runnable01 runnable01 = new Runnable01();
         *         new Thread(runnable01).start();
         *
         * 3）、实现 Callable 接口 + FutureTask （可以拿到返回结果，可以处理异常）
         *          FutureTask<Integer> integerFutureTask = new FutureTask<>(new Callable01());
         *         new Thread(integerFutureTask).start();
         *         //阻塞等待 等待整个线程执行完成，获取返回结果
         *         Integer integer = integerFutureTask.get();
         *
         *我们以后在业务代码里面，以上三种启动线程的方式都不用。将所有的多线程异步任务都交给线程池执行
         * 4）、线程池
         *          给线程池直接提交任务
         *          service.execute(new Runnable01());
         *        1、创建：
         *              1）、Executors
         *              2）、new ThreadPoolExecutor
         *        Future：可以获取到异步结果
         *区别：
         *       1、2、不能得到返回值。3、可以获取返回值
         *       1、2、3、都不能控制资源
         *       4、可以控制资源，性能稳定
         */
        /**
         * 七大参数
         *        corePoolSize[5]：核心线程数；线程池，创建好以后就准备就绪的线程数量，就等待来接受异步任务去执行
         *                  5个   Thread thread = new Thread();
         *                  池中一直保持的线程的数量，即使线程空闲。除非设置了 allowCoreThreadTimeOut
         *        maximumPoolSize 池中允许的最大的线程数  控制资源并发
         *        keepAliveTime：存活时间       当线程数大于核心线程数的时候，线程在最大多长时间没有接到新任务就会终止释放 ，
         *                                     最终线程池维持在 corePoolSize  大小
         *        unit时间单位
         *
         *        BlockingQueue<Runnable> workQueue：阻塞队列   如果任务有很多，就会将目前多的任务放在队列中
         *                                          只要有线程空闲，就会去队列中取出新的任务继续执行
         *        ThreadFactory threadFactory：线程的创建工厂，比如指定线程名等
         *        handler：拒绝策略，如果线程满了，线程池就会使用拒绝策略。
         *工作顺序：
         *  1）、线程池创建，准备好 core 数量的核心线程，准备接受任务
         *  2）、新的任务进来，用 core 准备好的空闲线程执行
         *      2.1、core 满了，就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队列获取任务执行
         *      2.2、阻塞队列满了，就直接开新线程执行，最大只能开到 max 指定的数量
         *      2.3、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自动销毁。最终保持到 core 大小
         *           new LinkedBlockingQueue<>(),:默认是Integer的最大值，内存不够
         *      2.4、如果线程数开到了 max 的数量，还有新任务进来，就会使用 reject 指定的拒绝策略进行处理
         *  3）、所有的线程创建都是由指定的 factory 创建的。
         * */

        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());


        System.out.println("main.....end.....");

    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }

    public static class Runnable01 implements Runnable {

        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }

    public static class Callable01 implements Callable<Integer> {


        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }
    }


}
